home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 22 / Amiga Format AFCD22 (Jan 1998, Issue 106).iso / -in_the_mag- / converters / graphics / netpbm / source1 / pgm / lispmtopgm.c < prev    next >
C/C++ Source or Header  |  1997-11-16  |  5KB  |  162 lines

  1. /* lispmtopgm.c - read a file written by the tv:write-bit-array-file function
  2. ** of TI Explorer and Symbolics Lisp Machines, and write a PGM.
  3. **
  4. ** Written by Jamie Zawinski based on code (C) 1988 by Jef Poskanzer.
  5. **
  6. ** Permission to use, copy, modify, and distribute this software and its
  7. ** documentation for any purpose and without fee is hereby granted, provided
  8. ** that the above copyright notice appear in all copies and that both that
  9. ** copyright notice and this permission notice appear in supporting
  10. ** documentation.  This software is provided "as is" without express or
  11. ** implied warranty.
  12. **
  13. **   When one writes a multi-plane bitmap with tv:write-bit-array-file, it is
  14. **   usually a color image; but a color map is not written in the file, so we
  15. **   treat this as a graymap instead.  Since the pgm reader can also read pbms,
  16. **   this doesn't matter if you're using only single plane images.
  17. */
  18.  
  19. #include <stdio.h>
  20. #include "pgm.h"
  21.  
  22. #define LISPM_MAGIC  "This is a BitMap file"
  23.  
  24. static void getinit ARGS(( FILE* file, short* colsP, short* rowsP, short* depthP, short* padrightP ));
  25. static int depth_to_word_size ARGS(( int depth ));
  26. static unsigned int getval ARGS(( FILE* file ));
  27.  
  28. int
  29. main( argc, argv )
  30.     int argc;
  31.     char* argv[];
  32.     {
  33.     FILE* ifp;
  34.     gray* grayrow;
  35.     register gray* gP;
  36.     short rows, cols, padright, row, col;
  37.     short depth;
  38.     int maxval;
  39.  
  40.  
  41.     pgm_init( &argc, argv );
  42.  
  43.     if ( argc > 2 )
  44.     pm_usage( "[lispmfile]" );
  45.  
  46.     if ( argc == 2 )
  47.         ifp = pm_openr( argv[1] );
  48.     else
  49.     ifp = stdin;
  50.  
  51.     getinit( ifp, &cols, &rows, &depth, &padright );
  52.     maxval = 1 << depth;
  53.  
  54.     if ( maxval > PGM_MAXMAXVAL )
  55.     pm_error( "depth is too large - try reconfiguring with PGM_BIGGRAYS" );
  56.  
  57.     pgm_writepgminit( stdout, cols, rows, (gray) maxval, 0 );
  58.     grayrow = pgm_allocrow( ( cols + 7 ) / 8 * 8 );
  59.  
  60.     for ( row = 0; row < rows; ++row )
  61.     {
  62.         for ( col = 0, gP = grayrow; col < cols; ++col, ++gP )
  63.         *gP = getval( ifp );
  64.     pgm_writepgmrow( stdout, grayrow, cols, (gray) maxval, 0 );
  65.     }
  66.     pm_close( ifp );
  67.     pm_close( stdout );
  68.     exit( 0 );
  69.     }
  70.  
  71. static long item, bitmask;
  72. static unsigned int bitsperitem, maxbitsperitem, bitshift;
  73.  
  74. static void
  75. getinit( file, colsP, rowsP, depthP, padrightP )
  76.     FILE* file;
  77.     short* colsP;
  78.     short* rowsP;
  79.     short* padrightP;
  80.     short* depthP;
  81.     {
  82.     short cols_32;
  83.     char magic[sizeof(LISPM_MAGIC)];
  84.     int i;
  85.  
  86.     for ( i = 0; i < sizeof(magic)-1; ++i )
  87.         magic[i] = getc( file );
  88.     magic[i]='\0';
  89.     if (0 != strcmp(LISPM_MAGIC, magic))
  90.         pm_error( "bad id string in Lispm file" );
  91.     
  92.     if ( pm_readlittleshort( file, colsP ) == -1 )
  93.         pm_error( "EOF / read error" );
  94.     if ( pm_readlittleshort( file, rowsP ) == -1 )
  95.         pm_error( "EOF / read error" );
  96.     if ( pm_readlittleshort( file, &cols_32 ) == -1 )
  97.         pm_error( "EOF / read error" );
  98.     *depthP = getc( file );
  99.     
  100.     if ( *depthP == 0 )
  101.     *depthP = 1;    /* very old file */
  102.     
  103.     *padrightP = ( ( *colsP + 31 ) / 32 ) * 32 - *colsP;
  104.     
  105.     if ( *colsP != (cols_32 - *padrightP) ) {
  106. /*    pm_message( "inconsistent input: Width and Width(mod32) fields don't agree" );  */
  107. /*    *padrightP = cols_32 - *colsP;   */ /*    hmmmm....   */
  108.       /* This is a dilemma.  Usually the output is rounded up to mod32, but not always.
  109.        * For the Lispm code to not round up, the array size must be the same size as the
  110.        * portion being written - that is, the array itself must be an odd size, not just
  111.        * the selected portion.  Since arrays that are odd sizes can't be handed to bitblt,
  112.        * such arrays are probably not image data - so punt on it for now.
  113.        *
  114.        * Also, the lispm code for saving bitmaps has a bug, in that if you are writing a
  115.        * bitmap which is not mod32 across, the file may be up to 7 bits too short!  They
  116.        * round down instead of up.
  117.        *
  118.        * The code in 'pgmtolispm.c' always rounds up to mod32, which is totally reasonable.
  119.        */
  120.       }
  121.     bitsperitem = 0;
  122.     maxbitsperitem = depth_to_word_size( *depthP );
  123.     bitmask = ( 1 << maxbitsperitem ) - 1;        /* for depth=3, mask=00000111 */
  124.  
  125.     for ( i = 0; i < 9; ++i )
  126.     getc( file );    /* discard bytes reserved for future use */
  127.     }
  128.  
  129. static int
  130. depth_to_word_size (depth)    /* Lispm architecture specific - if a bitmap is written    */
  131.   int depth;            /* out with a depth of 5, it really has a depth of 8, and  */
  132. {                /* is stored that way in the file.               */
  133.     if (depth==0 || depth==1)    return ( 1);
  134.     else if (depth ==  2)    return ( 2);
  135.     else if (depth <=  4)    return ( 4);
  136.     else if (depth <=  8)    return ( 8);
  137.     else if (depth <= 16)    return (16);
  138.     else if (depth <= 32)    return (32);
  139.     else
  140.       pm_error( "depth was %d, which is not in the range 1-32.", depth );
  141. }
  142.  
  143. static unsigned int
  144. getval( file )
  145.     FILE* file;
  146.     {
  147.     unsigned int b;
  148.  
  149.     if ( bitsperitem == 0 )
  150.     {
  151.     if ( pm_readlittlelong( file, &item ) == -1 )
  152.         pm_error( "EOF / read error" );
  153.     bitsperitem = 32;
  154.     bitshift = 0;
  155.     item = ~item;
  156.     }
  157.     b = ( ( item >> bitshift ) & bitmask );
  158.     bitsperitem = bitsperitem - maxbitsperitem;
  159.     bitshift = bitshift + maxbitsperitem;
  160.     return b;
  161.     }
  162.